package com.panshi.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro配置类<br>
 *   该类主要初始化启动装载Shiro类对象，完成相关实例化工作，为后面功能提供服务
 */
@Configuration
public class ShiroConfig {

    @Bean
    public DefaultWebSecurityManager securityManager(SysUserRealm userRealm) {

        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();

        //设置用户域
        defaultSecurityManager.setRealm(userRealm);

        //设置记住密码管理
        defaultSecurityManager.setRememberMeManager(cookieRememberMeManager());

        //创建了一个session管理器
        defaultSecurityManager.setSessionManager(defaultWebSessionManager());


        ThreadContext.bind(defaultSecurityManager);//解决异常：ThreadContext or as a vm static singleton

        return defaultSecurityManager;

    }

    /**
     *   配置shiro过滤器后，相当于servlet的filter<br>
     *   1、页面才能正常使用shiro相关标签，不然使用无效，如< shiro:principal property="username"/>   <br>
     *   2、其他类获取SysUserPO sysUserPO=(SysUserPO)SecurityUtils.getSubject().getPrincipal();才不会报错<br>
     * @param securityManager
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {

        //创建一个过滤工厂Bean,跟我们以前web用的过滤器类似
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //注入安全管理类
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //设置登录页面路径
        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置没有权限访问进入路径
        shiroFilterFactoryBean.setUnauthorizedUrl("/notAuth");

        //创建一个过滤路径map对象,key是路径，value值说明：anon代表匿名访问，authc代表必须登录subject.login认证后授权后才能访问
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //放开static静态文件路径不授权就可以访问，如果不放开，相关js，css将无法访问
        filterChainDefinitionMap.put("/static/**", "anon");
        //放开执行登录操作
        filterChainDefinitionMap.put("/login", "anon");
        //退出登录操作
        filterChainDefinitionMap.put("/loginout", "logout");

        //放开验证码的路径
        filterChainDefinitionMap.put("/verifyCode/**","anon");

        //authc其他所有路径都必须通过subject.login认证后才能访问
        //filterChainDefinitionMap.put("/**", "authc");
        //如果用了rememberMe记住我功能，那就必须把authc改成user,否则记住我功能失效，必须要记住了
        filterChainDefinitionMap.put("/**", "user");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;

    }

    /**
     * Shiro 整合thymeleaf框架，加这个注解后才能使用标签，如<br>
     * < shiro:principal property="username"/><br>
     * @return
     */
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    //<===============RememberMe配置==================>
    /**
     * Cookie记住我管理器
     * @return
     */
    public RememberMeManager cookieRememberMeManager(){

        CookieRememberMeManager cookieRememberMeManager=new CookieRememberMeManager();

        //rememberMe cookie加密的密钥  默认AES算法 密钥长度(128 256 512 位)
        //6BvVHd5gUs0FEA86DFAdAg== 是密码钥匙，建议每个项目都不一样

        cookieRememberMeManager.setCipherKey(Base64.decode("6BvVHd5gUs0FEA86DFAdAg=="));

        //设置cookie
        cookieRememberMeManager.setCookie(simpleCookie());
        return cookieRememberMeManager;
    }

    /**
     *  自定义指定cookie多少天，如果没有操作的情况下自动过期
     * @return
     */
    @Bean
    public SimpleCookie simpleCookie() {
        //创建一个cookie名称
        SimpleCookie simpleCookie=new SimpleCookie("rememberMe");
        simpleCookie.setMaxAge(2592000);//单位秒，折算成30天
        return simpleCookie;
    }

    /**
     *  创建一个session管理器，解决重定向自动带有;jsessionid=0935FAEB578E70CDB29AA08303F91C69
     * @return
     */
    public DefaultWebSessionManager defaultWebSessionManager(){
        DefaultWebSessionManager defaultWebSessionManager=new DefaultWebSessionManager();
        //移除重定向不自动带有;jsessionid=0935FAEB578E70CDB29AA08303F91C69功能

        defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);

        return defaultWebSessionManager;

    }


}
